package net.anzix.jhacks.flexclipse.properties;

import java.util.ArrayList;
import java.util.List;

import net.anzix.jhacks.flexclipse.Activator;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.osgi.service.prefs.BackingStoreException;

public class ProjectPropertyLoader {
	final IProject project;

	final IScopeContext context;
	final IEclipsePreferences node;

	public static final String flexclipsePropertyFileName = ".flexclipse";
	public static final String MAINMXML_PROPERTY = "flexclipse.main-mxml";
	public static final String DEFAULT_MAINMXML = "src/flex/Main.mxml";
	public static final String OUTPUT_PROPERTY = "flexclipse.output";
	public static final String DEFAULT_OUTPUT = "out.swf";
	public static final String LIBS_PROPERTY = "flexclipse.libraries";
	public static final List<String> DEFAULT_LIBS = new ArrayList<String>();

	public static final String OPTIMIZE_PROPERTY = "flexclipse.optimize";
	public static final String DEFAULT_OPTIMIZE = "false";

	public ProjectPropertyLoader(final IProject project) {
		this.project = project;
		this.context = new ProjectScope(project);
		this.node = context.getNode(Activator.PLUGIN_ID);
	}

	List<String> getProperty(final String key, final List<String> def) {
		final String storedValue = node.get(key, serializeList(def));
		return deserializeList(storedValue);
	}

	String getProperty(final String key, final String def) {
		final String storedValue = node.get(key, def);
		return storedValue;
	}

	boolean getProperty(final String key, final boolean def) {
		final String storedValue = node.get(key, def ? Boolean.TRUE.toString()
				: Boolean.FALSE.toString());
		return Boolean.parseBoolean(storedValue);
	}

	void setProperty(final String key, final List<String> value,
			final List<String> def) {
		if (def == null || def.equals(value)) {
			node.remove(key);
		} else {
			String val = serializeList(value);
			node.put(key, val);
		}
	}

	private List<String> deserializeList(final String value) {
		final ArrayList<String> ret = new ArrayList<String>();
		final String[] split = value.split(",");
		for (final String lib : split) {
			ret.add(lib);
		}
		return ret;
	}

	private String serializeList(final List<String> value) {
		final StringBuffer buffer = new StringBuffer();
		boolean first = true;
		for (final String lib : value) {
			if (!first) {
				buffer.append(',');
			} else {
				first = false;
			}
			buffer.append(lib);
		}
		String val = buffer.toString();
		return val;
	}

	void setProperty(final String key, final String value, final String def) {
		if (def == null) {
			setNullDefProperty(key, value);
		} else {
			setNonNullDefProperty(key, value, def);
		}
	}

	void setProperty(final String key, final boolean value, final boolean def) {
		if (value == def) {
			node.remove(key);
		} else {
			node.put(key, Boolean.toString(value));
		}
	}

	private void setNonNullDefProperty(final String key, final String value,
			final String def) {
		if (def.equals(value)) {
			// keep the properties as small as possible
			// so remove the defaults
			node.remove(key);
		} else {
			node.put(key, value);
		}
	}

	private void setNullDefProperty(final String key, final String value) {
		if (value == null) {
			// keep the properties as small as possible
			// so remove the defaults
			node.remove(key);
		} else {
			node.put(key, value);
		}
	}

	public void persistProperties(final IProgressMonitor monitor)
			throws BackingStoreException {
		node.flush();
	}

	public String getMainMxml() {
		return getProperty(MAINMXML_PROPERTY, DEFAULT_MAINMXML);
	}

	public void setMainMxml(final String mainMxml) {
		setProperty(MAINMXML_PROPERTY, mainMxml, DEFAULT_MAINMXML);
	}

	public String getOutput() {
		return getProperty(OUTPUT_PROPERTY, DEFAULT_OUTPUT);
	}

	public void setOutput(final String output) {
		setProperty(OUTPUT_PROPERTY, output, DEFAULT_OUTPUT);
	}

	public List<String> getLibraries() {
		return getProperty(LIBS_PROPERTY, DEFAULT_LIBS);
	}

	public void setLibraries(List<String> libraries) {
		setProperty(LIBS_PROPERTY, libraries, DEFAULT_LIBS);
	}

	public boolean isOptimize() {
		return getProperty(OPTIMIZE_PROPERTY, false);
	}

	public void setOptimize(boolean optimize) {
		setProperty(OPTIMIZE_PROPERTY, optimize, false);
	}

}
